package com.mumu.muPictureBackend.manager.upload;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.mumu.muPictureBackend.exception.BusinessException;
import com.mumu.muPictureBackend.exception.ErrorCode;
import com.mumu.muPictureBackend.exception.ThrowUtils;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

/**
 * 通过URL地址来上传图片文件
 */
@Service
public class URLPictureUpload extends PictureUploadTemplate {
    @Override
    public void transferToLocalFile(Object inputSource, File file) throws IOException {
        String URL = (String) inputSource;
        HttpUtil.downloadFile(URL, file);
    }

    /**
     * 从URL中提取原始文件名
     *
     * @param inputSource
     * @return
     */
    @Override
    public String getOriginalFilename(Object inputSource) {
        String URL = (String) inputSource;
//        这里要手动给url拼上后缀名 这里在校验文件格式的时候format就获取了该文件的后缀名 如果format为null 那么就给定默认的jpeg即可
        if (format == null) {
            format = "jpeg";
        }
        if(URL.length()>100){
            return "Picture";
        }
        return FileUtil.getName(URL) + "." + format;
    }


    String format = null;

    /**
     * 校验URL是否合格
     *
     * @param inputSource
     */
    @Override
    public void ValidPicture(Object inputSource) {

        String fileUrl = (String) inputSource;
        //1. 判断是否非空
        ThrowUtils.throwIf(StrUtil.isBlank(fileUrl), ErrorCode.PARAMS_ERROR);
        //2. 判断格式是否合格 这里直接new一个URL如果报错了 就标识不是一个合格的url地址
        try {
            new URL(fileUrl);
        } catch (MalformedURLException e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "url地址不合格");
        }
        //3. 判断是不是http/https开头的
        ThrowUtils.throwIf(!fileUrl.startsWith("http://") && !fileUrl.startsWith("https://"), ErrorCode.PARAMS_ERROR, "只支持http,https协议的url");
        //4. 使用HEAD请求去请求这个fileUrl 只返回响应头header 不返回实际内容(直接快速判断该url地址是否存在 不需要下载整个文件) 并且这个header中还包含该文件的类型,大小等信息可以快速判断 不过有些图片就是本身不带有head所以如果没有head就不校验类型和大小了
        HttpResponse httpResource = null;
        try {
            //获取HEAD请求:快速利用HEAD来判断该url是否存在
            httpResource = HttpUtil.createRequest(Method.HEAD, fileUrl)
                    .execute();
//            如果响应码不等于200 那么就说明不存在/该url内容存在但是没有响应头 那么就直接返回 不用进行下面的校验了
            if (httpResource.getStatus() != HttpStatus.HTTP_OK) {
                return;
            }
            // 因为有的URL是没有请求头的 所以没有请求头直接放行不校验 但是有请求头的话就简单校验一下类型还有大小即可 请求头中包含了文件大小类型
            //如果该文件有请求头 那么请求头中还包含该文件的类型,httpResource.header("Content-Type")就是获取文件类型 请求头里面还包含该文件的大小
            //请求头存在 那么就要校验文件类型,大小
            String contentType = httpResource.header("Content-Type");
//          校验文件类型
            if (StrUtil.isNotBlank(contentType)) {
                final Map<String, String> ALLOW_CONTENT_TYPES = Map.of(
                        "image/jpeg", "jpg",
                        "image/jpg", "jpg",
                        "image/png", "png",
                        "image/gif", "gif",
                        "image/webp", "webp",
                        "image/bmp", "bmp"
                );//定义格式 都是image/开头的
                ThrowUtils.throwIf(ALLOW_CONTENT_TYPES.get(contentType) == null, ErrorCode.PARAMS_ERROR, "只支持常规图片格式");
                format = ALLOW_CONTENT_TYPES.get(contentType);
            }
//            校验文件大小
            String lengthStr = httpResource.header("Content-Length");
            if (StrUtil.isNotBlank(lengthStr)) {
                long length = Long.parseLong(lengthStr);
                final long ONE_M = 1024 * 1024;
                ThrowUtils.throwIf(length > 10 * ONE_M, ErrorCode.PARAMS_ERROR, "文件太大了 不要超过2M");
            }


        } finally {
//            释放资源
            if (httpResource != null) {
                httpResource.close();
            }
        }

    }
}
